package com.fjh.springboot_01.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.fjh.springboot_01.config.AlipayConfig;
import com.fjh.springboot_01.mapper.PaymentOrderMapper;
import com.fjh.springboot_01.pojo.payment.PaymentOrder;
import com.fjh.springboot_01.pojo.tutor.Tutoring;
import com.fjh.springboot_01.pojo.tutor.TutoringBooking;
import com.fjh.springboot_01.pojo.tutor.TutoringSchedule;
import com.fjh.springboot_01.service.PaymentService;
import com.fjh.springboot_01.service.TutoringService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentOrderMapper paymentOrderMapper;
    
    @Autowired
    private TutoringService tutoringService;
    
    @Autowired
    private AlipayConfig alipayConfig;
    
    @Autowired
    private AlipayClient alipayClient;
    
    @Override
    @Transactional
    public PaymentOrder createPaymentOrder(Integer bookingId) {
        // 查询已存在的订单
        PaymentOrder existingOrder = paymentOrderMapper.findByBookingId(bookingId);
        if (existingOrder != null && existingOrder.getStatus() != 2) {
            // 如果已经存在订单且不是支付失败状态，直接返回
            return existingOrder;
        }
        
        // 获取预约信息
        TutoringBooking booking = tutoringService.getBookingById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预约信息不存在");
        }
        
        if (booking.getStatus() != 1) {
            throw new RuntimeException("只有已接受的预约才能进行支付");
        }
        
        // 获取家教信息，主要是拿到价格
        Tutoring tutoring = tutoringService.getTutoringById(booking.getTutoringId());
        if (tutoring == null) {
            throw new RuntimeException("家教信息不存在");
        }
        
        // 创建支付订单
        PaymentOrder paymentOrder = new PaymentOrder();
        paymentOrder.setOrderNo(generateOrderNo());
        paymentOrder.setBookingId(bookingId);
        paymentOrder.setTutoringId(booking.getTutoringId());
        paymentOrder.setStudentId(booking.getStudentId());
        paymentOrder.setTeacherId(booking.getTeacherId());
        paymentOrder.setAmount(tutoring.getHourlyRate());
        paymentOrder.setStatus(0); // 未支付
        paymentOrder.setPaymentMethod("alipay");
        paymentOrder.setCreateTime(LocalDateTime.now());
        paymentOrder.setUpdateTime(LocalDateTime.now());
        
        // 插入支付订单
        paymentOrderMapper.insert(paymentOrder);
        
        // 重新查询以获取完整信息（包括关联的用户名和课程标题）
        PaymentOrder completeOrder = paymentOrderMapper.findByOrderNo(paymentOrder.getOrderNo());
        
        return completeOrder;
    }
    
    @Override
    public String createAlipayForm(String orderNo) {
        PaymentOrder order = paymentOrderMapper.findByOrderNo(orderNo);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        
        // 获取家教信息
        Tutoring tutoring = tutoringService.getTutoringById(order.getTutoringId());
        if (tutoring == null) {
            throw new RuntimeException("家教信息不存在");
        }
        
        // 使用注入的AlipayClient，不再创建新实例
        
        // 创建API请求对象
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        // 设置回调地址
        alipayRequest.setReturnUrl(alipayConfig.getReturnUrl());
        alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());
        
        // 构建订单参数
        String title = "Physics Tutoring";
        String totalAmount = order.getAmount().toString();
        
        // 组装请求参数
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", order.getOrderNo());
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        bizContent.put("total_amount", totalAmount);
        bizContent.put("subject", title);
        bizContent.put("body", "Tutoring Fee");
        
        // 使用JSON工具类序列化成JSON字符串，避免字符编码问题
        String bizContentJson = JSON.toJSONString(bizContent, SerializerFeature.WriteMapNullValue);
        alipayRequest.setBizContent(bizContentJson);
        
        String form = "";
        try {
            // 调用支付宝接口，获取支付表单
            form = alipayClient.pageExecute(alipayRequest).getBody();
            System.out.println("Generated Alipay form: " + form);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("创建支付表单失败: " + e.getMessage());
        }
        
        return form;
    }
    
    @Override
    @Transactional
    public boolean handleAlipayNotify(Map<String, String> params) {
        try {
            System.out.println("收到支付宝回调通知: " + params);
            
            // 1. 验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params,
                    alipayConfig.getPublicKey(),
                    alipayConfig.getCharset(),
                    alipayConfig.getSignType());
            
            if (!signVerified) {
                System.out.println("支付宝回调签名验证失败");
                return false;
            }
            System.out.println("支付宝回调签名验证成功");
            
            // 2. 验证app_id是否为本应用的app_id
            if (!params.get("app_id").equals(alipayConfig.getAppId())) {
                System.out.println("应用ID不匹配, 收到的app_id: " + params.get("app_id") + ", 配置的app_id: " + alipayConfig.getAppId());
                return false;
            }
            System.out.println("应用ID匹配验证成功");
            
            // 3. 获取交易状态
            String tradeStatus = params.get("trade_status");
            String outTradeNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            
            System.out.println("订单号: " + outTradeNo + ", 交易状态: " + tradeStatus + ", 支付宝交易号: " + tradeNo);
            
            // 4. 交易成功状态
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                PaymentOrder order = paymentOrderMapper.findByOrderNo(outTradeNo);
                if (order == null) {
                    System.out.println("订单不存在: " + outTradeNo);
                    return false;
                }
                
                // 打印当前订单状态
                System.out.println("当前订单状态: " + order.getStatus() + ", 订单ID: " + order.getId());
                
                // 如果已经是支付成功状态，直接返回成功
                if (order.getStatus() == 1) {
                    System.out.println("订单已经是支付成功状态, 订单号: " + outTradeNo);
                    return true;
                }
                
                // 5. 更新订单状态
                System.out.println("更新订单状态为支付成功, 订单号: " + outTradeNo);
                int updatedRows = paymentOrderMapper.updatePaymentStatus(
                        outTradeNo,
                        1, // 支付成功
                        tradeNo,
                        LocalDateTime.now(),
                        LocalDateTime.now()
                );
                
                System.out.println("更新订单状态结果: 影响行数=" + updatedRows);
                
                // 再次查询订单状态，确认更新是否成功
                PaymentOrder updatedOrder = paymentOrderMapper.findByOrderNo(outTradeNo);
                if (updatedOrder != null) {
                    System.out.println("更新后订单状态: " + updatedOrder.getStatus() + ", 交易号: " + updatedOrder.getTradeNo());
                } else {
                    System.out.println("无法查询到更新后的订单");
                }
                
                System.out.println("支付成功处理完成");
                return true;
            }
            
            System.out.println("交易状态不是成功状态: " + tradeStatus);
            return false;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            System.out.println("支付宝回调处理异常: " + e.getMessage());
            return false;
        }
    }
    
    @Override
    public PaymentOrder getPaymentOrderByOrderNo(String orderNo) {
        return paymentOrderMapper.findByOrderNo(orderNo);
    }
    
    @Override
    public List<PaymentOrder> getStudentPaymentOrders(Integer studentId) {
        return paymentOrderMapper.findByStudentId(studentId);
    }
    
    @Override
    public List<PaymentOrder> getTeacherPaymentOrders(Integer teacherId) {
        return paymentOrderMapper.findByTeacherId(teacherId);
    }
    
    @Override
    @Transactional
    public PaymentOrder createPaymentOrderByScheduleId(Integer scheduleId) {
        // 查询课程安排信息
        TutoringSchedule schedule = tutoringService.getScheduleById(scheduleId);
        if (schedule == null) {
            throw new RuntimeException("课程安排不存在");
        }
        
        // 更新条件：已确认(1)或已完成(2)状态的课程才能进行支付
        if (schedule.getStatus() != 1 && schedule.getStatus() != 2) {
            throw new RuntimeException("只有已确认或已完成的课程安排才能进行支付");
        }
        
        // 检查是否已经存在针对该课程安排的支付订单
        List<PaymentOrder> existingOrders = paymentOrderMapper.findByStudentId(schedule.getStudentId());
        String scheduleIdStr = String.valueOf(scheduleId);
        
        for (PaymentOrder order : existingOrders) {
            // 检查该订单是否与当前课程安排匹配
            if (order.getTeacherId().equals(schedule.getTeacherId())) {
                // 还需确认是否是为这个具体的课程安排创建的支付订单
                if ((order.getBookingId() != null && schedule.getBookingId() != null && 
                     order.getBookingId().equals(schedule.getBookingId())) ||
                    // 支付备注中可能包含课程安排ID
                    (order.getOrderNo() != null && order.getOrderNo().contains("SCH" + scheduleIdStr))) {
                    
                    // 如果已经存在订单且不是支付失败状态，直接返回
                    if (order.getStatus() != 2) {
                        return order;
                    }
                }
            }
        }
        
        // 查询家教信息，主要是拿到价格
        Tutoring tutoring = tutoringService.getTutoringById(schedule.getTutoringId());
        if (tutoring == null) {
            throw new RuntimeException("家教信息不存在");
        }
        
        // 创建支付订单
        PaymentOrder paymentOrder = new PaymentOrder();
        
        // 在订单编号中包含课程安排ID标识，便于后续查询
        paymentOrder.setOrderNo(generateOrderNoWithScheduleId(scheduleId));
        
        // 处理bookingId - 数据库要求不能为null
        if (schedule.getBookingId() != null) {
            // 如果课程安排有关联的预约ID，直接使用
            paymentOrder.setBookingId(schedule.getBookingId());
        } else {
            // 尝试根据学生和教师ID找到一个有效的预约ID
            TutoringBooking booking = tutoringService.findBookingByStudentAndTeacherId(
                    schedule.getStudentId(), schedule.getTeacherId());
            
            if (booking != null) {
                // 找到相关预约，使用其ID
                paymentOrder.setBookingId(booking.getId());
            } else {
                // 如果实在找不到相关预约，创建一个特殊的ID标记
                // 可以使用课程安排ID作为预约ID的一种方式
                paymentOrder.setBookingId(scheduleId);
                // 另一种做法是抛出异常
                // throw new RuntimeException("无法创建支付订单：找不到关联的预约信息");
            }
        }
        
        paymentOrder.setTutoringId(schedule.getTutoringId());
        paymentOrder.setStudentId(schedule.getStudentId());
        paymentOrder.setTeacherId(schedule.getTeacherId());
        paymentOrder.setAmount(tutoring.getHourlyRate());
        paymentOrder.setStatus(0); // 未支付
        paymentOrder.setPaymentMethod("alipay");
        paymentOrder.setCreateTime(LocalDateTime.now());
        paymentOrder.setUpdateTime(LocalDateTime.now());
        
        // 插入支付订单
        paymentOrderMapper.insert(paymentOrder);
        
        // 重新查询以获取完整信息（包括关联的用户名和课程标题）
        PaymentOrder completeOrder = paymentOrderMapper.findByOrderNo(paymentOrder.getOrderNo());
        
        return completeOrder;
    }
    
    /**
     * 生成包含课程安排ID的订单编号
     * 格式：年月日时分秒+SCH+课程安排ID+4位随机数
     * @param scheduleId 课程安排ID
     * @return 订单编号
     */
    private String generateOrderNoWithScheduleId(Integer scheduleId) {
        String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 4);
        return dateStr + "SCH" + scheduleId + uuid;
    }
    
    /**
     * 生成订单编号
     * 格式：年月日时分秒+6位随机数
     * @return 订单编号
     */
    private String generateOrderNo() {
        String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 6);
        return dateStr + uuid;
    }
    
    @Override
    @Transactional
    public int manualUpdatePaymentStatus(String orderNo, String tradeNo) {
        System.out.println("手动更新订单支付状态: 订单号=" + orderNo + ", 交易号=" + tradeNo);
        
        // 先查询订单信息，确保订单存在
        PaymentOrder order = paymentOrderMapper.findByOrderNo(orderNo);
        if (order == null) {
            System.out.println("订单不存在，无法更新状态");
            return 0;
        }
        
        // 如果订单已经是支付成功状态，直接返回成功
        if (order.getStatus() == 1) {
            System.out.println("订单已经是支付成功状态，无需更新");
            return 1;
        }
        
        // 更新订单状态
        int rows = paymentOrderMapper.updatePaymentStatus(
                orderNo,
                1, // 支付成功
                tradeNo,
                LocalDateTime.now(),
                LocalDateTime.now()
        );
        
        System.out.println("手动更新订单状态结果: 影响行数=" + rows);
        
        // 再次查询订单，确认更新是否成功
        PaymentOrder updatedOrder = paymentOrderMapper.findByOrderNo(orderNo);
        if (updatedOrder != null) {
            System.out.println("更新后订单状态: " + updatedOrder.getStatus() + 
                    ", 交易号: " + updatedOrder.getTradeNo() + 
                    ", 支付时间: " + updatedOrder.getPaymentTime());
        }
        
        return rows;
    }
} 